package mybatis.interceptor.example.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.ognl.Ognl;
import org.apache.ibatis.ognl.OgnlContext;
import org.apache.ibatis.plugin.*;
import org.springframework.util.StopWatch;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @author guan.xin
 * @title TpTenantWriteInterceptor
 * @description
 * @create 2022-04-21 13:17
 * @since JDK8
 */
@Slf4j
@Intercepts(value = {
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
})
public class TpTenantWriteInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        MappedStatement statement = (MappedStatement) invocation.getArgs()[0];
        BoundSql sql = statement.getBoundSql(invocation.getArgs()[1]);

        List<ParameterMapping> list = sql.getParameterMappings();
        OgnlContext context = (OgnlContext) Ognl.createDefaultContext(sql.getParameterObject());
        List<Object> params = new ArrayList<>(list.size());
        for (ParameterMapping mapping : list) {
            params.add(Ognl.getValue(Ognl.parseExpression(mapping.getProperty()), context, context.getRoot()));
        }
        try {
            return invocation.proceed();
        } finally {
            stopWatch.stop();
            log.info("sql: {}", "TpTenantWriteInterceptor");
            log.info("sql: {}", sql.getSql());
            log.info("args: {}", params);
            log.info("cost: {}", stopWatch.getLastTaskInfo().getTimeMillis());
        }
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}
